﻿using BizTalk.ESB.Extensions.SSO.Common;
using BizTalk.ESB.Extensions.SSO.Data;
using Microsoft.EnterpriseSingleSignOn.Interop;
using System;
using System.Collections;
using System.Linq;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace BizTalk.ESB.Extensions.SSO.Utility
{
    class Program
    {
        #region Response Messages

        const string RemoveFail_Message = "Failed to remove SSO Application.";
        const string ImportSuccess_Message = "Import Complete.";
        const string RemoveSuccess_Message = "Application SSO Configuration has been removed.";
        const string ApplicationNameNullEmpty_Message = "Application Name provided is NULL or EMPTY.";
        const string FileNameNullEmpty_Message = "File Name provided is NULL or EMPTY.";
        const string ImportFail_ApplicationExists_Message = "Import Failed.  Application already exists.  Please remove then re-import.";
        const string ImportFail_ApplicationName_Message = "Import Failed.  No Application Name specified in import file.";
        const string ImportFail_AdminGroup_Message = "Import Failed.  Invalid BizTalk Administration Group Name.";
        const string ImportFail_UserGroup_Message = "Import Failed.  Invalid BizTalk Application Users Group Name.";

        #endregion

        static void Main(string[] args)
        {
            if (args.Length < 2 || args.Length > 4)
            {
                PrintUsage();
                return;
            }

            Console.WriteLine("Arguement: " + args[0] + ", " + args[1]);
            String command = args[0].ToUpper();

            if (command != "IMPORT" && command != "REMOVE" && command != "EXPORT" && command != "UPDATE")
            {
                PrintUsage();
                return;
            }

            String msg = String.Empty;
            switch (command)
            {
                case ("IMPORT"):
                    {
                        if (args.Length == 4)
                        {
                            msg = Import(args[1], args[2], args[3]);
                        }
                        else
                        {
                            msg = Import(args[1]);
                        }
                        break;
                    }
                case ("UPDATE"):
                    {
                        if (args.Length == 4)
                        {
                            msg = Update(args[1], args[2], args[3]);
                        }
                        else
                        {
                            msg = Update(args[1]);
                        }
                        break;
                    }
                case ("EXPORT"):
                    {
                        msg = Export(args[1], args[2]);
                        break;
                    }
                case ("REMOVE"):
                    {
                        msg = Remove(args[1]);
                        break;
                    }
            }
            Console.WriteLine(msg);
        }

        static string Update(string FileName)
        {
            string returnmsg = String.Empty;
            var app = new SsoApplication();

            // Load XML from file path
            var xmlSsoImport = new XmlDocument();
            xmlSsoImport.Load(FileName);

            // Deserialize XML to SSO Object
            var serializer = new DataContractSerializer(typeof(SsoApplication));
            var reader = new XmlNodeReader(xmlSsoImport.DocumentElement);
            app = (SsoApplication)serializer.ReadObject(reader);

            var config = new SsoConfigStore();
            if (String.IsNullOrEmpty(app.ApplicationName))
            {
                returnmsg = ImportFail_ApplicationName_Message;
            }
            else
            {
                if (!config.AppExists(app.ApplicationName))
                {
                    config.CreateSsoApplication(app);
                    returnmsg = ImportSuccess_Message + " Application: " + app.ApplicationName;
                }
                else
                {
                    Remove(app.ApplicationName);
                    returnmsg = RemoveSuccess_Message;
                    config.CreateSsoApplication(app);
                    returnmsg = returnmsg + " -- " + ImportSuccess_Message + " Application: " + app.ApplicationName;
                }
            }
            return returnmsg;
        }

        static string Update(string FileName, string AdminGroupName, string AppUserGroupName)
        {
            string returnmsg = String.Empty;
            var app = new SsoApplication();

            // Load XML from file path
            var xmlSsoImport = new XmlDocument();
            xmlSsoImport.Load(FileName);

            // Deserialize XML to SSO Object
            var serializer = new DataContractSerializer(typeof(SsoApplication));
            var reader = new XmlNodeReader(xmlSsoImport.DocumentElement);
            app = (SsoApplication)serializer.ReadObject(reader);

            var config = new SsoConfigStore();
            if (String.IsNullOrEmpty(app.ApplicationName))
            {
                returnmsg = ImportFail_ApplicationName_Message;
            }
            if (String.IsNullOrEmpty(AdminGroupName))
            {
                returnmsg = ImportFail_AdminGroup_Message;
            }
            if (String.IsNullOrEmpty(AppUserGroupName))
            {
                returnmsg = ImportFail_UserGroup_Message;
            }
            else
            {
                if (!config.AppExists(app.ApplicationName))
                {
                    app.AdminGroup = AdminGroupName;
                    app.UserGroup = AppUserGroupName;
                    config.CreateSsoApplication(app);
                    returnmsg = ImportSuccess_Message + " Application: " + app.ApplicationName;
                }
                else
                {
                    Remove(app.ApplicationName);
                    returnmsg = RemoveSuccess_Message;
                    app.AdminGroup = AdminGroupName;
                    app.UserGroup = AppUserGroupName;
                    config.CreateSsoApplication(app);
                    returnmsg = returnmsg + " -- " + ImportSuccess_Message + " Application: " + app.ApplicationName;
                }
            }
            return returnmsg;
        }

        static String Import(string FileName)
        {
            string returnmsg = String.Empty;
            var app = new SsoApplication();

            // Load XML from file path
            var xmlSsoImport = new XmlDocument();
            xmlSsoImport.Load(FileName);

            // Deserialize XML to SSO Object
            var serializer = new DataContractSerializer(typeof(SsoApplication));
            var reader = new XmlNodeReader(xmlSsoImport.DocumentElement);
            app = (SsoApplication)serializer.ReadObject(reader);

            var config = new SsoConfigStore();
            if (String.IsNullOrEmpty(app.ApplicationName))
            {
                returnmsg = ImportFail_ApplicationName_Message;
            }
            else
            {
                if (!config.AppExists(app.ApplicationName))
                {
                    config.CreateSsoApplication(app);
                    returnmsg = ImportSuccess_Message + " Application: " + app.ApplicationName;
                }
                else
                {
                    returnmsg = ImportFail_ApplicationExists_Message + " Application: " + app.ApplicationName;
                }
            }
            return returnmsg;
        }

        static string Import(string FileName, string AdminGroupName, string AppUserGroupName)
        {
            string returnmsg = String.Empty;
            var app = new SsoApplication();

            // Load XML from file path
            var xmlSsoImport = new XmlDocument();
            xmlSsoImport.Load(FileName);

            // Deserialize XML to SSO Object
            var serializer = new DataContractSerializer(typeof(SsoApplication));
            var reader = new XmlNodeReader(xmlSsoImport.DocumentElement);
            app = (SsoApplication)serializer.ReadObject(reader);

            var config = new SsoConfigStore();
            if (String.IsNullOrEmpty(app.ApplicationName))
            {
                returnmsg = ImportFail_ApplicationName_Message;
            }
            if (String.IsNullOrEmpty(AdminGroupName))
            {
                returnmsg = ImportFail_AdminGroup_Message;
            }
            if (String.IsNullOrEmpty(AppUserGroupName))
            {
                returnmsg = ImportFail_UserGroup_Message;
            }
            else
            {
                if (!config.AppExists(app.ApplicationName))
                {
                    app.AdminGroup= AdminGroupName;
                    app.UserGroup = AppUserGroupName;
                    config.CreateSsoApplication(app);
                    returnmsg = ImportSuccess_Message + " Application: " + app.ApplicationName;
                }
                else
                {
                    returnmsg = ImportFail_ApplicationExists_Message + " Application: " + app.ApplicationName;
                }
            }
            return returnmsg;
        }

        static string Export(string ApplicationName, string FileName)
        {
            string ReturnMsg = String.Empty;
            if (String.IsNullOrEmpty(ApplicationName))
            {
                ReturnMsg = ApplicationNameNullEmpty_Message;
            }
            else
            {
                if (String.IsNullOrEmpty(FileName))
                {
                    ReturnMsg = FileNameNullEmpty_Message;
                }
                else
                {
                    var app = new SsoApplication();
                    var config = new SsoConfigStore();
                    if (config.AppExists(ApplicationName))
                    {
                        config.GetSsoApplication(ApplicationName);
                        ReturnMsg = "Application:" + ApplicationName + " SSO Configuration Exported.";
                    }
                    else
                    {
                        ReturnMsg = "Application with name " + ApplicationName + " does not exist in the SSO Configuration Store.";
                    }
                }
            }
            return ReturnMsg;
        }

        static string Remove(string ApplicationName)
        {
            var config = new SsoConfigStore();
            try
            {
                config.DeleteSsoApplication(ApplicationName);
                return RemoveSuccess_Message;
            }
            catch (Exception)
            {
                return RemoveFail_Message;
            }
        }

        static private void PrintUsage()
        {
            Console.WriteLine("Usage:");
            Console.WriteLine();
            Console.WriteLine("ESB.SSO.Utility <import|export|remove> <File Name|Application Name> [File Name]");
            Console.WriteLine();
            Console.WriteLine(" Where: ");
            Console.WriteLine("  <File Name> = The xml file containing configuration information that needs to be imported or exported.");
            Console.WriteLine();
            Console.WriteLine("Example: ESB.SSO.Utility import SSOAppConfig.xml");
            Console.WriteLine("Example: ESB.SSO.Utility import SSOAppConfig.xml BTAdminGroupName BTAppUserGroupName");
            Console.WriteLine(@"Example: ESB.SSO.Utility export BizTalkAppWithSsoConfig C:\SSOConfigFile.xml");
            Console.WriteLine("Example: ESB.SSO.Utility remove BizTalkAppWithSsoConfig");
            Console.WriteLine();
        }
    }
}
